#include "ThreadPool.h"
#include "api.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int RLEencode(const char *src, int src_len, char *dst)
{
    char cur = src[0];
    char cnt = 1;
    int i, ptr = 0;
    for (i = 1; i < src_len; ++i)
    {
        if (src[i] == cur)
        {
            ++cnt;
        }
        else
        {
            dst[ptr] = cur;
            dst[ptr + 1] = cnt;
            ptr += 2;
            cur = src[i];
            cnt = 1;
        }
    }
    dst[ptr] = cur;
    dst[ptr + 1] = cnt;
    ptr += 2;
    return ptr;
}

char *file_encoder(const char *f_path, int *dst_len)
{
    int fd = -1, f_len = 0;
    void *mmap_ptr;
    struct stat file_stat;

    fd = open(f_path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
    if (fd == -1)
    {
        printf("Open file failed: %s\n", strerror(errno));
        return NULL;
    }
    if (fstat(fd, &file_stat) == -1)
    {
        printf("Get file stat failed: %s\n", strerror(errno));
        close(fd);
        return NULL;
    }
    f_len = file_stat.st_size;
    if (f_len == 0)
    {
        close(fd);
        return NULL;
    }

    // printf("len = %d\n", f_len);

    mmap_ptr = mmap(0, f_len, PROT_READ, MAP_SHARED, fd, 0);
    if (mmap_ptr == (void *)-1)
    {
        printf("mmap failed: %s\n", strerror(errno));
        return NULL;
    }
    close(fd);

    // printf("%s\n", (char*)mmap_ptr);

    char *dst = (char *)malloc(sizeof(char) * f_len * 2);
    memset(dst, 0, sizeof(char) * f_len * 2);

    *dst_len = RLEencode((const char *)mmap_ptr, f_len, dst);

    // printf("%s", dst);

    munmap(mmap_ptr, f_len);

    return dst;
}

void multi_file_single_thread_RLEencode(int file_cnt, char **file_path)
{
    char **encodeed = (char **)malloc(sizeof(char *) * file_cnt);
    int *encodeed_len = (int *)malloc(sizeof(int) * file_cnt);
    int i, sum_len = 0, ptr = 0;

    for (i = 0; i < file_cnt; ++i)
    {
        encodeed[i] = file_encoder(file_path[i], encodeed_len + i);
    }

    for (i = 0; i < file_cnt; ++i)
    {
        sum_len += encodeed_len[i];
        // printf("encodeed_len[%d] = %d\n", i, encodeed_len[i]);
        // printf("%s\n", encodeed[i]);
    }

    char *ans = (char *)malloc(sizeof(char) * (sum_len + 2));
    memset(ans, 0, sizeof(char) * (sum_len + 2));

    strcpy(ans, encodeed[0]);
    free(encodeed[0]);
    ptr += encodeed_len[0];
    for (i = 1; i < file_cnt; ++i)
    {
        if (ans[ptr - 2] == encodeed[i][0])
        {
            encodeed[i][1] += ans[ptr - 1];
            strcpy(ans + ptr - 2, encodeed[i]);
            ptr -= 2;
            ptr += encodeed_len[i];
        }
        else
        {
            strcpy(ans + ptr, encodeed[i]);
            ptr += encodeed_len[i];
        }
        free(encodeed[i]);
    }
    free(encodeed);
    free(encodeed_len);
    printf("%s", ans);
    free(ans);
}
